#!/usr/bin/perl -w

# The setup.* routines will eventually be folded into larger scripts 
# that configure the cluster or an application as a whole.
#
# This one will configure the name of the cluster - even if it
# is already set...
#
# The return values are:
# 0 - ports allocated as required
# 1 - no work was needed
# 2 - an error has occured - see STDERR

BEGIN {
	if(!exists($::ENV{TRUECL_CODE})) {
		die("Missing TRUECL_CODE environment variable.");
	}
	if(!exists($::ENV{TRUECL_LOG})) {
		die("Missing TRUECL_LOG environment variable.");
	}
	if(!exists($::ENV{TRUECL_CFG})) {
		die("Missing TRUECL_CFG environment variable.");
	}
	if(! -d "$::ENV{TRUECL_CODE}/clreqd_modules") {
		die("Missing clreqd_modules directory in $::ENV{TRUECL_CODE}.");
	}
	push @::INC,"$::ENV{TRUECL_CODE}/lib";
	$::PKI=1;
	eval "use Crypt::RSA;";
	$::PKI=0 if $@;
}

$::PKI=1;
if($::PKI==1 && exists($::ENV{TRUECL_PKI})) {
	$::PKI=$::ENV{TRUECL_PKI};
}

sub usage {
	print "
Usage: setup.cluster-name [--force] [--timeout N] [--parallel] [--width N] NAME
";
	exit 1;
}

use strict;
use Getopt::Long;
use common_requests;
use clreqdxml;
use cllogging;
use Data::Dumper;

$::ARG_timeout=10;
$::ARG_force=0;
$::ARG_width=80;
$::ARG_parallel=0;
$::ARG_recreate=0;

if(!GetOptions(
	"recreate"	=> \$::ARG_recreate,
	"timeout=i"	=> \$::ARG_timeout,
	"width=i"	=> \$::ARG_width,
	"parallel"	=> \$::ARG_parallel,
	"force"		=> \$::ARG_force,
)) {
	usage;
}

if(!exists($ARGV[0])) {
	usage;
}

$::ARG_name=$ARGV[0];

#########################################################################
# Put in command line argument processing here and a usage msg.		#
#########################################################################

$::LOGGER=new cllogging("-",$::ARG_width);

if(!defined($::LOGGER)) {
	print STDERR "Error: Unable to initialise logging object.\n";
	exit 1;
}

$::LOGGER->set_verbose;
$::CLREQD=new clreqdxml("$::ENV{TRUECL_CFG}/clreqd.xml");
if(!defined($::CLREQD)) {
	$::LOGGER->msg("error","Unable to open/parse file $::ENV{TRUECL_CFG}/clreqd.xml - aborting.");
	$::LOGGER->msg("error","MSG from object: ".clreqdxml->error);
	exit 1;
}
$::LOGGER->msg("msg","Initialised 'cluster request daemon interface' object successfully.");

$::COMMON=new common_requests(timeout=>$::ARG_timeout,parallel=>$::ARG_parallel,clreqdxml=>$::CLREQD);
if(!defined($::COMMON)) {
	$::LOGGER->msg("error","Unable to initialise 'common requests' object.");
	exit 1;
}

$::LOGGER->msg("msg","Initialised 'common requests' object successfully.");


#########################################################################
# At this point we've got to do some real work!! - Setting the cluster	#
# name - if it is not already set - unless --recreate is set.		#
#########################################################################

{
	my ($list,$err);
	if(!$::ARG_recreate) {
		#########################################################
		# Before attempting to set the clustername, check to	#
		# see if the name is not already set and abort if so.	#
		#########################################################
		($list,$err)=$::COMMON->run_config_sql(sql =>"SELECT value FROM globals WHERE var = 'clustername';",force=>$::ARG_force);
		#########################################################
		# If all hosts return undef values then no value is	#
		# set. If certain hosts return values double check they	#
		# are all the same and if not abort!!			#
		#########################################################

		if(!defined($list)) {
			$::LOGGER->msg("error"," [$err]");
			exit 2;
		}
		
		my $chost;
		my $clustername=undef;
		for $chost (sort(keys(%$list))) {
			if(!defined($list->{$chost})) {
				next;
			}
			$list->{$chost}=~s/^value[\s\n]+//;
			if(defined($clustername) && $list->{$chost} ne $clustername) {
				$::LOGGER->msg("error","Cluster name mismatch - aborting.");

				exit 2;
			}
			$clustername=$list->{$chost} if !defined($clustername);
		}
		if(defined($clustername)) {
			$::LOGGER->msg("error","Cluster name already configured - aborting.");
			exit 2;
		}
	}

	#################################################################
	# If we get here we want to set the cluster name .. even if it	#
	# is already set.						#
	#################################################################

	$::LOGGER->msg("msg","Setting cluster name to '$::ARG_name'.");
	($list,$err)=$::COMMON->run_config_sql(sql =>"INSERT OR REPLACE INTO globals (var,value) VALUES ('clustername','$::ARG_name');",force=>$::ARG_force);
	if(!defined($list)) {
		$::LOGGER->msg("error","No results returned from attempting to set cluster name.");
		$::LOGGER->msg("error"," [$err]");
		exit 2;
	}
	my $chost;
	my $errs=0;
	my $clustername=undef;
	for $chost (sort(keys(%$list))) {
		if(!defined($list->{$chost})) {
			$::LOGGER->msg("error","No results returned from '$chost'.");
			$errs++;
			next;
		}
		$::LOGGER->msg('msg',"$chost: $list->{$chost}");
	}
	exit(1) if $errs;
}
exit(0);
